/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package controladores;

import controladores.exceptions.IllegalOrphanException;
import controladores.exceptions.NonexistentEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import entidades.Usuario;
import entidades.Tipo;
import entidades.Comentario;
import entidades.Objeto;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;

/**
 *
 * @author Fran
 */
public class ObjetoJpaController implements Serializable {

    public ObjetoJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Objeto objeto) {
        if (objeto.getComentarioCollection() == null) {
            objeto.setComentarioCollection(new ArrayList<Comentario>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Usuario usuario = objeto.getUsuario();
            if (usuario != null) {
                usuario = em.getReference(usuario.getClass(), usuario.getId());
                objeto.setUsuario(usuario);
            }
            Tipo tipo = objeto.getTipo();
            if (tipo != null) {
                tipo = em.getReference(tipo.getClass(), tipo.getId());
                objeto.setTipo(tipo);
            }
            Collection<Comentario> attachedComentarioCollection = new ArrayList<Comentario>();
            for (Comentario comentarioCollectionComentarioToAttach : objeto.getComentarioCollection()) {
                comentarioCollectionComentarioToAttach = em.getReference(comentarioCollectionComentarioToAttach.getClass(), comentarioCollectionComentarioToAttach.getId());
                attachedComentarioCollection.add(comentarioCollectionComentarioToAttach);
            }
            objeto.setComentarioCollection(attachedComentarioCollection);
            em.persist(objeto);
            if (usuario != null) {
                usuario.getObjetoCollection().add(objeto);
                usuario = em.merge(usuario);
            }
            if (tipo != null) {
                tipo.getObjetoCollection().add(objeto);
                tipo = em.merge(tipo);
            }
            for (Comentario comentarioCollectionComentario : objeto.getComentarioCollection()) {
                Objeto oldObjetoOfComentarioCollectionComentario = comentarioCollectionComentario.getObjeto();
                comentarioCollectionComentario.setObjeto(objeto);
                comentarioCollectionComentario = em.merge(comentarioCollectionComentario);
                if (oldObjetoOfComentarioCollectionComentario != null) {
                    oldObjetoOfComentarioCollectionComentario.getComentarioCollection().remove(comentarioCollectionComentario);
                    oldObjetoOfComentarioCollectionComentario = em.merge(oldObjetoOfComentarioCollectionComentario);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Objeto objeto) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Objeto persistentObjeto = em.find(Objeto.class, objeto.getId());
            Usuario usuarioOld = persistentObjeto.getUsuario();
            Usuario usuarioNew = objeto.getUsuario();
            Tipo tipoOld = persistentObjeto.getTipo();
            Tipo tipoNew = objeto.getTipo();
            Collection<Comentario> comentarioCollectionOld = persistentObjeto.getComentarioCollection();
            Collection<Comentario> comentarioCollectionNew = objeto.getComentarioCollection();
            List<String> illegalOrphanMessages = null;
            for (Comentario comentarioCollectionOldComentario : comentarioCollectionOld) {
                if (!comentarioCollectionNew.contains(comentarioCollectionOldComentario)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Comentario " + comentarioCollectionOldComentario + " since its objeto field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (usuarioNew != null) {
                usuarioNew = em.getReference(usuarioNew.getClass(), usuarioNew.getId());
                objeto.setUsuario(usuarioNew);
            }
            if (tipoNew != null) {
                tipoNew = em.getReference(tipoNew.getClass(), tipoNew.getId());
                objeto.setTipo(tipoNew);
            }
            Collection<Comentario> attachedComentarioCollectionNew = new ArrayList<Comentario>();
            for (Comentario comentarioCollectionNewComentarioToAttach : comentarioCollectionNew) {
                comentarioCollectionNewComentarioToAttach = em.getReference(comentarioCollectionNewComentarioToAttach.getClass(), comentarioCollectionNewComentarioToAttach.getId());
                attachedComentarioCollectionNew.add(comentarioCollectionNewComentarioToAttach);
            }
            comentarioCollectionNew = attachedComentarioCollectionNew;
            objeto.setComentarioCollection(comentarioCollectionNew);
            objeto = em.merge(objeto);
            if (usuarioOld != null && !usuarioOld.equals(usuarioNew)) {
                usuarioOld.getObjetoCollection().remove(objeto);
                usuarioOld = em.merge(usuarioOld);
            }
            if (usuarioNew != null && !usuarioNew.equals(usuarioOld)) {
                usuarioNew.getObjetoCollection().add(objeto);
                usuarioNew = em.merge(usuarioNew);
            }
            if (tipoOld != null && !tipoOld.equals(tipoNew)) {
                tipoOld.getObjetoCollection().remove(objeto);
                tipoOld = em.merge(tipoOld);
            }
            if (tipoNew != null && !tipoNew.equals(tipoOld)) {
                tipoNew.getObjetoCollection().add(objeto);
                tipoNew = em.merge(tipoNew);
            }
            for (Comentario comentarioCollectionNewComentario : comentarioCollectionNew) {
                if (!comentarioCollectionOld.contains(comentarioCollectionNewComentario)) {
                    Objeto oldObjetoOfComentarioCollectionNewComentario = comentarioCollectionNewComentario.getObjeto();
                    comentarioCollectionNewComentario.setObjeto(objeto);
                    comentarioCollectionNewComentario = em.merge(comentarioCollectionNewComentario);
                    if (oldObjetoOfComentarioCollectionNewComentario != null && !oldObjetoOfComentarioCollectionNewComentario.equals(objeto)) {
                        oldObjetoOfComentarioCollectionNewComentario.getComentarioCollection().remove(comentarioCollectionNewComentario);
                        oldObjetoOfComentarioCollectionNewComentario = em.merge(oldObjetoOfComentarioCollectionNewComentario);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = objeto.getId();
                if (findObjeto(id) == null) {
                    throw new NonexistentEntityException("The objeto with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Objeto objeto;
            try {
                objeto = em.getReference(Objeto.class, id);
                objeto.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The objeto with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Collection<Comentario> comentarioCollectionOrphanCheck = objeto.getComentarioCollection();
            for (Comentario comentarioCollectionOrphanCheckComentario : comentarioCollectionOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Objeto (" + objeto + ") cannot be destroyed since the Comentario " + comentarioCollectionOrphanCheckComentario + " in its comentarioCollection field has a non-nullable objeto field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Usuario usuario = objeto.getUsuario();
            if (usuario != null) {
                usuario.getObjetoCollection().remove(objeto);
                usuario = em.merge(usuario);
            }
            Tipo tipo = objeto.getTipo();
            if (tipo != null) {
                tipo.getObjetoCollection().remove(objeto);
                tipo = em.merge(tipo);
            }
            em.remove(objeto);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Objeto> findObjetoEntities() {
        return findObjetoEntities(true, -1, -1);
    }

    public List<Objeto> findObjetoEntities(int maxResults, int firstResult) {
        return findObjetoEntities(false, maxResults, firstResult);
    }

    private List<Objeto> findObjetoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Objeto.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Objeto findObjeto(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Objeto.class, id);
        } finally {
            em.close();
        }
    }

    public int getObjetoCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Objeto> rt = cq.from(Objeto.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
